package leetcode.editor.cn.dsa01_array;
//验证给定的字符串是否可以解释为十进制数字。
//
// 例如: 
//
// "0" => true 
//" 0.1 " => true 
//"abc" => false 
//"1 a" => false 
//"2e10" => true 
//" -90e3 " => true 
//" 1e" => false 
//"e3" => false 
//" 6e-1" => true 
//" 99e2.5 " => false 
//"53.5e93" => true 
//" --6 " => false 
//"-+3" => false 
//"95a54e53" => false 
//
// 说明: 我们有意将问题陈述地比较模糊。在实现代码之前，你应当事先思考所有可能的情况。这里给出一份可能存在于有效十进制数字中的字符列表： 
//
// 
// 数字 0-9 
// 指数 - "e" 
// 正/负号 - "+"/"-" 
// 小数点 - "." 
// 
//
// 当然，在输入中，这些字符的上下文也很重要。 
//
// 更新于 2015-02-10: 
//C++函数的形式已经更新了。如果你仍然看见你的函数接收 const char * 类型的参数，请点击重载按钮重置你的代码。 
// Related Topics 数学 字符串 
// 👍 161 👎 0
/*
先设定numSeen，dotSeen和eSeen三种boolean变量，分别代表是否出现数字、点和E
然后遍历目标字符串
1.判断是否属于数字的0~9区间
2.遇到点的时候，判断前面是否有点或者E，都需要return false
3.遇到E的时候，判断前面数字是否合理，是否有E，并把numSeen置为false，防止E后无数字
4.遇到-+的时候，判断是否是第一个，如果不是第一个判断是否在E后面，都不满足则return false
5.其他情况都为false
最后返回numSeen的结果即可
 */
public class ValidNumber65{
    public static void main(String[] args) {
        Solution solution = new ValidNumber65().new Solution();
        System.out.println(solution.isNumber("1 a")); //false
        System.out.println(solution.isNumber("2e10")); //true
        System.out.println(solution.isNumber("-90e3   ")); //true
        System.out.println(solution.isNumber(" 1e")); //false
        System.out.println(solution.isNumber("e3")); //false
        System.out.println(solution.isNumber(" 6e-1")); //true
        System.out.println(solution.isNumber(" 99e2.5 ")); //false
        System.out.println(solution.isNumber("53.5e93")); //true
        System.out.println(solution.isNumber(" --6 ")); //false
        System.out.println(solution.isNumber("-3e+")); //false
        System.out.println(solution.isNumber("-3e3+")); //false
        System.out.println(solution.isNumber(".21")); //true
    }
    //leetcode submit region begin(Prohibit modification and deletion)
    class Solution {
        /**
         * 只能包含：数字、正负号、e、点号，允许前后有空白
         * 1.点和e不能出现多次
         * 2.e前后都要有数字
         * 3.+-号要么在最前要么紧挨e后(前后都只能有一个)
         * 4.e后面不能有小数点
         * 注意：点前面可以没有数字，比如 .1
         */
        public boolean isNumber(String s) {
            if(s == null || s.length() == 0) return false;
            boolean numSeen = false; // 普通数字
            boolean dotSeen = false; // 点号
            boolean eSeen = false; // 指数：e
            char[] array = s.trim().toCharArray();
            for (int i = 0; i < array.length; i++) {
                char c = array[i];
                if(c >= '0' && c <= '9'){
                    numSeen = true;
                }else if(c == '.'){
                    // 前面不能有e，点不能重复
                    if(eSeen || dotSeen){
                       return false;
                    }
                    dotSeen = true;
                }else if(c == 'e' || c == 'E') {
                    // e前一定要有数字，e不能重复
                    if(!numSeen || eSeen){
                        return false;
                    }
                    eSeen = true;
                    // 怎么判断e后有没有数字？
                    // 技巧：e出现后让数字重置为false，如果最后数字为true则正常
                    numSeen = false;
                }else if(c == '+' || c == '-') {
                    // 正负号只能在第一个位置或者e后的第一个位置，位置判断保证了不会重复
                    if(i != 0 && array[i-1] != 'E' && array[i-1] != 'e'){
                        return false;
                    }
                }else{ // 不能出现其他字符
                    return false;
                }
            }
            if(!numSeen){
                return false;
            }
            return true;
        }
    }
    //leetcode submit region end(Prohibit modification and deletion)
}